package webservice.utils;

import javax.net.ssl.*;
import java.io.*;
import java.net.HttpURLConnection;
import java.net.ProtocolException;
import java.net.URL;
import java.security.KeyManagementException;
import java.security.NoSuchAlgorithmException;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;
import java.util.logging.Level;
import java.util.logging.Logger;


public class WebServiceHttpConnect {

    //配置连接超时(单位：毫秒) 默认10000毫秒
    private Integer connectTimeout=10000;

    private static final Logger LOGGER = Logger.getLogger("WebServiceHttpConnect");
    public WebServiceHttpConnect(){}

    private Map<String,String> requestHeader=new HashMap<>();
    public WebServiceHttpConnect(Integer connectTimeout){
        this.connectTimeout=connectTimeout;
    }

    public WebServiceHttpConnect addRequestHeader(String key,String value){
        requestHeader.put(key,value);
        return this;
    }

    public ResponseExample soap12HttpSend(String urlStr,String soapXml){
        return soap11HttpSend(urlStr,soapXml,null);
    }



    public ResponseExample soap11HttpSend(String urlStr,String soapXml,String SOAPAction){
        return wsHttpRequest( urlStr, soapXml, SOAPAction,RequestState.WS_HTTP);
    }



    public ResponseExample soap11HttpsSend(String urlStr,String soapXml,String SOAPAction){
        return wsHttpRequest( urlStr, soapXml,SOAPAction,RequestState.WS_HTTPS);
    }

    public ResponseExample soap12HttpsSend(String urlStr,String soapXml){
        return soap11HttpsSend(urlStr,soapXml,null);
    }

    private ResponseExample wsHttpRequest(String urlStr,String soapXml,String SOAPAction,Integer state){
        OutputStream os=null;
        ResponseExample responseExample=null;
        try {
            long start = System.currentTimeMillis();
            URL url=new URL(urlStr);
            HttpURLConnection connection=getConnection(state,url);
            setHttpURLConnection(connection, SOAPAction);
            os = connection.getOutputStream();
            os.write(soapXml.getBytes());
            responseExample=readResponseData(connection);
            long finish = System.currentTimeMillis();
            LOGGER.info("webService调用耗时为"+(finish-start)+"ms,请求地址:"+urlStr);
        }catch (Exception e){
            LOGGER.log(Level.WARNING,"Exception caught",e);
        }finally {
            if (os!=null){
                try {
                    os.close();
                } catch (IOException e) {
                    LOGGER.log(Level.WARNING,"The output stream is closed abnormally");
                }
            }
        }
        return responseExample;
    }


    private HttpURLConnection getConnection(Integer state,URL url) throws IOException, NoSuchAlgorithmException, KeyManagementException {
        if (Objects.equals(state, RequestState.WS_HTTP)){
            return (HttpURLConnection) url.openConnection();
        }else {
            skipSSL();
            return (HttpsURLConnection) url.openConnection();
        }
    }


    private ResponseExample readResponseData(HttpURLConnection connection) throws IOException {
        try (
                InputStream is = connection.getInputStream();
                InputStreamReader isr = new InputStreamReader(is);
                BufferedReader br = new BufferedReader(isr)
             ){
            StringBuilder sb = new StringBuilder();
            String temp=null;
            while ((temp=br.readLine())!=null){
                sb.append(temp);
            }
            int responseCode = connection.getResponseCode();
            String context = sb.toString();
            if (responseCode!=200){
                LOGGER.log(Level.WARNING,"您或许有一处错误,错误代码:"+responseCode+"错误信息为:"+connection.getResponseMessage());
            }
            return new ResponseExample(responseCode,context);
        }catch (IOException e){
            LOGGER.log(Level.WARNING,"您或许有一处错误,错误代码:"+connection.getResponseCode()+"错误信息为:"+connection.getResponseMessage());
            return new ResponseExample(connection.getResponseCode(),connection.getResponseMessage());
        }
    }

    private void setHttpURLConnection(HttpURLConnection connection,String SOAPAction) throws ProtocolException {
        connection.setConnectTimeout(this.connectTimeout);
        connection.setRequestMethod("POST");

        connection.setDoInput(true);
        connection.setDoOutput(true);
        if (SOAPAction!=null){
            connection.setRequestProperty("content-type" , "text/xml; charset=utf-8");
            connection.setRequestProperty("SOAPAction", SOAPAction);
        }else {
            connection.setRequestProperty("content-type" , "application/soap+xml; charset=utf-8");
        }
        if (!this.requestHeader.isEmpty()){
            for (Map.Entry<String, String> next : requestHeader.entrySet()) {
                System.out.println(next.getKey()+next.getValue());
                connection.setRequestProperty(next.getKey(), next.getValue());
            }
        }
    }


    /**
     * 跳过所有的ssl认证
     */
    private void skipSSL() throws NoSuchAlgorithmException, KeyManagementException {
        // 创建一个信任所有证书的TrustManager
        TrustManager[] trustAllCerts = new TrustManager[]{
                new X509TrustManager() {
                    public java.security.cert.X509Certificate[] getAcceptedIssuers() {
                        return null;
                    }

                    public void checkClientTrusted(
                            java.security.cert.X509Certificate[] certs, String authType) {
                    }

                    public void checkServerTrusted(
                            java.security.cert.X509Certificate[] certs, String authType) {
                    }
                }
        };
        SSLContext sc = SSLContext.getInstance("SSL");
        sc.init(null, trustAllCerts, new java.security.SecureRandom());
        HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory());

        // 创建一个HostnameVerifier，并设置它
        HostnameVerifier allHostsValid = new HostnameVerifier() {
            public boolean verify(String hostname, SSLSession session) {
                return true;
            }
        };

        // 安装所有主机名验证器
        HttpsURLConnection.setDefaultHostnameVerifier(allHostsValid);
    }
}
